package fregat.connector.channel;


import java.util.Vector;

import fregat.connector.ConnectorService;

/**
 * Abstract base class for a channel.
 *
 * @author Alexander Mann <br><b><i>ECO_L O G</i> &nbsp Logistiksysteme GmbH</b>
 * @version 1.0
 */
public abstract class AbstractChannel {

  private Vector listeners; // list of instances listening on this channel
  private String name; // configuration name
  private static int instances; // number of active channels

  /**
   * Initializes the channel.
   *
   * @param name Configuration name of channel
   */
  public AbstractChannel(String name) {
    this.name = name;
    listeners = new Vector();
  }

  /**
   * Sends data over the channel.
   *
   * @param data Any message
   * @return True, if send was success
   */
  public abstract boolean send(byte[] data);

  /**
   * Starts the communication on the channel.
   */
  public void start() {
    for (int i = 0; i < listeners.size(); i++) {
      ((ChannelListener) listeners.elementAt(i)).start();
    }
    instances++;
  }

  /**
   * Stops the communication on the channel.
   */
  public void shutdown() {
    for (int i = 0; i < listeners.size(); i++) {
      ((ChannelListener) listeners.elementAt(i)).shutdown();
    }
    instances--;
  }

  /**
   * Informs listeners about connection state.
   *
   * @param b True, if connected
   */
  public void connected(boolean b) {
    for (int i = 0; i < listeners.size(); i++) {
      ((ChannelListener) listeners.elementAt(i)).connected(b);
    }
  }

  /**
   * @return Configuration name of the channel
   */
  public String getName() {
    return name;
  }

  /**
   * Adds a listener that should receive data on that channel.
   *
   * @param listener
   */
  public void addListener(ChannelListener listener) {
    listeners.add(listener);
  }

  /**
   * This method is called, when data was received. The received data is
   * forwarded to all connected listeners.
   *
   * @param data Received data
   */
  public boolean received(byte[] data) {
    try {
      boolean receiveOk = true;

      for (int i = 0; i < listeners.size(); i++) {
        // forward data to listener
        receiveOk &= ((ChannelListener) listeners.elementAt(i)).received(AbstractChannel.this.getName(), data);
      }
      return receiveOk;
    } catch (Exception ex) {
      ConnectorService.error(getName() + ", AbstractChannel.received", ex);
      return false;
    }
  }

  /**
   * @return Configuration name of channel
   */
  public String toString() {
    return "'" + getName() + "'";
  }

  /**
   * @return Number of active channels
   */
  public static int getInstances() {
    return instances;
  }

  /**
   * This method may be called by worker to signal that all data was sent.
   */
  public void dataComplete() {
  }
}
